package bayes;

import engine.Stats;
import engine.Tweet;
import engine.Tweet.Brand;
import engine.Tweet.Polarity;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;
import java.util.TreeMap;
import javax.swing.SwingWorker;
import normalisation.Normalizer;
import ui.UserInterface;
import utilities.FileTools;

public class BayesSwing extends SwingWorker<Void, Integer> {

    private UserInterface gui;
    private String filePath;
    private Normalizer normalizer;
    private Double[] aPriorisPolarity;//l'a priori de chaque classe
    private Double sucessRatePolarity, sucessRateBrand;
    private String outputPath;
    private Integer[][] matriceConfusion;
    private Integer penalityPoints;
    private String fileTrain;
    private boolean modeleBinomial;
    private Double[] coeffsAntiPenality;

    public BayesSwing(UserInterface gui,
            String filePath,
            String fileTrain,
            Normalizer normalizer,
            Double[] coeffsAntiPenality,
            String outputPath,
            boolean modeleBinomial) {

        this.gui = gui;
        this.filePath = filePath;
        this.outputPath = outputPath;
        this.normalizer = normalizer;
        this.matriceConfusion = new Integer[Polarity.values().length][Polarity.values().length];
        this.penalityPoints = 0;
        this.fileTrain = fileTrain;
        this.modeleBinomial = modeleBinomial;
        this.coeffsAntiPenality = coeffsAntiPenality;
    }

   public void executeBayes() throws IOException{
       //Parcours de chaque ligne
        List<String> lines = FileTools.readLinesTextFile(filePath, normalizer.getCharset());
        ArrayList<Tweet> listTweet = new ArrayList<Tweet>();
        Polarity currentPolarity;
        Brand currentBrand;
        Integer rigthGuessPolarity = 0;
        //init matrice confusion
        for (int i = 0; i < matriceConfusion.length; i++) {
            for (int j = 0; j < matriceConfusion.length; j++) {
                matriceConfusion[i][j] = 0;
            }
        }

        Writer writer = (outputPath != null) ? new OutputStreamWriter(new FileOutputStream(outputPath)) : new OutputStreamWriter(System.out);

        for (String line : lines) {
            //System.out.println("\nline: " + (lineCount + 1));

            //suppression première parenthèse (doit être le premier caractère)
            line = line.substring(1);

            //parse la polarité
            currentPolarity = Stats.parsePolarity(line.substring(0, line.indexOf(",")));
            line = line.substring(line.indexOf(",") + 1);//on supprime "polarité,"

            //parse la marque
            currentBrand = Stats.parseBrand(line.substring(0, line.indexOf(")")));
            line = line.substring(line.indexOf(")") + 2);//on supprime "marque) "
            
            //Crée Tweet
            Tweet t = new Tweet();
            t.setBrand(currentBrand);
            t.setContenu(line);
            t.setPolarity(currentPolarity);
            listTweet.add(t);
        }
        Classifieur c;
        if(modeleBinomial) {
        	c = new BayesienBinomial(coeffsAntiPenality);
        }else {
        	c = new BayesienMultinomial(coeffsAntiPenality);
        }
        c.train(fileTrain, normalizer);
        ArrayList<Integer> lstPolarity = c.determinerPolarite(listTweet);

        for (int i = 0; i < lstPolarity.size(); i++) {
            int bestPolId = lstPolarity.get(i);
            Polarity bestPol = Polarity.values()[bestPolId];
            Tweet t = listTweet.get(i);

            if (t.getPolarity() == bestPol) {
                rigthGuessPolarity++;
            }
            else{
                //System.out.println((i+1) + " : " + bestPol + " (" + t.getPolarity() + ") ");
            }

            matriceConfusion[bestPolId][t.getPolarity().ordinal()]++;

            if (writer != null) {
                writer.write(bestPol.toString() + "\n");
            }

        }
        if (writer != null) {
            writer.close();
        }

        sucessRatePolarity = (double) rigthGuessPolarity * 100 / lines.size();
        //sucessRateBrand = (double) rigthGuessBrand * 100 / lines.size();
        sucessRateBrand = -1.;//non calculé

        //calcul des points de penalité
        Integer[][] matricePenalite = {
            {0, 2, 3, 3},
            {2, 0, 3, 3},
            {4, 4, 0, 1},
            {4, 4, 1, 0},};

        for (int i = 0; i < matriceConfusion.length - 1; i++) {
            for (int j = 0; j < matriceConfusion.length - 1; j++) {
                this.penalityPoints += matriceConfusion[i][j] * matricePenalite[i][j];
            }
        }

        //Affichage matrice confusion
//        System.out.println("Matrice de Confusion: ");
//
//        System.out.print("     ");
//        for (int i = 0; i < Polarity.values().length - 1; i++) {
//            System.out.print(Polarity.values()[i].toString().substring(0, 5) + " ");
//        }
//        System.out.println("     ");
//        for (int i = 0; i < matriceConfusion.length - 1; i++) {
//            System.out.print(Polarity.values()[i].toString().substring(0, 5));
//            for (int j = 0; j < matriceConfusion.length - 1; j++) {
//                System.out.format(" %4d ", matriceConfusion[i][j]);
//            }
//            System.out.println("");
//        }
   }

	@Override
    protected Void doInBackground() throws Exception {
        executeBayes();
        return null;
    }

    @Override
    protected void done() {
        //System.out.println("Done BinomSwing");
        if(gui != null) gui.updateBayesResult(sucessRatePolarity, sucessRateBrand, penalityPoints);
    }
}
